#ifndef _AVRSTDC_COMMON_H_
#define _AVRSTDC_COMMON_H_
/*******************************************************************************
 ** Name: common.h                                                            **
 ** Description:                                **
 **                                                                           **
 ** Open Source Initiative (OSI) Approved License: CDDL                       **
 **                                                                           **
 ** The contents of this file are subject to the terms of the                 **
 ** Common Development and Distribution License, Version 1.0 only             **
 ** (the "License").  You may not use this file except in compliance          **
 ** with the License.                                                         **
 **                                                                           **
 ** You can find a copy of the license in the license.txt within              **
 ** this distribution or at http://opensource.org/licenses/CDDL-1.0.          **
 ** Software distributed under the License is distributed on an "AS IS"       **
 ** basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.           **
 ** See the License for the specific language governing permissions           **
 ** and limitations under the License.                                        **
 **                                                                           **
 ** When distributing Covered Code, include this CDDL header in each          **
 ** file and include the License file at license.{pdf|rtf|otf}.               **
 ** If applicable, add the following below this header, with the indicated    **
 ** fields enclosed by brackets "[]" replaced with your own identifying       **
 ** information: Portions Copyright [yyyy] [name of copyright owner]          **
 **                                                                           **
 ** Copyright (c) 2009-2010  Barry Gian James <bjames@avr-firmware.net>       **
 ** All rights reserved.                                                      **
 **                                                                           **
 ** Ref: $HeadURL: https://munix.svn.codeplex.com/svn/trunk/libmunix/common.h $
 ******************************************************************************/
// Portions (C) 2011-13 Open Design Strategies, LLC.
// All Rights Reserved

// $Id: common.h 69249 2012-08-28 18:42:19Z unknown $
// Last Modified $Date$ by $Author: unknown $

#define _MUNIX_COMMON_ID    "$Id: common.h 7 2010-07-14 12:58:31Z nevdull69 $"

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>

 #ifdef __AVR__
#include <avr/io.h>
#include "types.h"
 #endif



// If you don't set F_CPU in your application, it defaults to 20MHz
#ifndef F_CPU
#define F_CPU 20000000
#endif

// This just makes my life easier
//#define BIT16(b) ((unsigned long)0x00000001 << (b))
#define BIT32(b) ((uint32)0x00000001 << (b))
#define BIT16(b) ((uint16)0x0001 << (b))
#define	BIT8(b) (0x01 << (b))

// from AVR035: Efficient C Coding for AVR
#define BSET(ADDRESS,BIT) (ADDRESS |= (unsigned char)(1<<BIT))
#define BCLR(ADDRESS,BIT) (ADDRESS &= (unsigned char)~(1<<BIT))
#define BTOG(ADDRESS,BIT) (ADDRESS ^= (unsigned char)(1<<BIT))
#define BCHK(ADDRESS,BIT) (ADDRESS &  (unsigned char)(1<<BIT))

#define BMSET(x,y) (x |= (y))
#define BMCLR(x,y) (x &= (~y))
#define BMTOG(x,y) (x ^= (y))
#define BMCHK(x,y) (x & (y))

#ifndef Max
#define Max(x,y) ((x)>=(y)?(x):(y))
#endif

#ifndef Min
#define Min(x,y) ((x)<=(y)?(x):(y))
#endif

#ifndef Abs
#define Abs(x) ((x) < 0 ? -(x) : (x))
#endif

#ifndef PI
#define PI 3.1415927
#endif

//typedef uint8_t		uint8;
//typedef uint16_t	uint16;
//typedef uint32_t	uint32;
//typedef unsigned char uchar;
//typedef unsigned long   time_t;
//typedef unsigned char byte;

#define __STDCPP_NORETURN__ __attribute__((__noreturn__))

#ifdef __AVR__
// C++ Sanity Wrappers
#define __nop()                       (asm volatile("nop\n\t"::))
#define BEGIN_CRITICAL_SECTION()    (asm volatile("ldi r16, SREG\n\tcli\n\t"::))
#define END_CRITICAL_SECTION()      (asm volatile("out SREG, r16\n\tsei\n\t"::))
//#define BEGIN_CRITICAL_SECTION()    (volatile uint8 __sregSave = SREG, cli())
//#define END_CRITICAL_SECTION()      (SREG = __sregSave, sei())
#define FNAME()				cout << __PRETTY_FUNCTION__ << endl

#ifdef USE_SMALL_MODEL
	typedef uint8_t	size_type;
#else
	typedef int	size_type;
#endif

// This works since gcc cpp 3.2
#ifdef USE_NAMESPACE
#define BEGIN_NAMESPACE(n)		\
		namespace n{
#else
#define BEGIN_NAMESPACE(n)
#endif

#ifdef USE_NAMESPACE
#define END_NAMESPACE()			}
#else
#define END_NAMESPACE()
#endif

//////////////////////// [ C++ Safety functions
__extension__ typedef int __guard __attribute__ ((mode (__DI__)));
#ifdef __cplusplus
extern "C" {
#endif
void __cxa_pure_virtual(void) { while(1); }
#if !defined(NO_THREADSAFE_STATICS)
int  __cxa_guard_acquire(__guard *g) {return !*(char*)(g); }
void __cxa_guard_release(__guard *g) {*(char*)g = 1; }
void __cxa_guard_abort(__guard*g) { }
#endif  /* !NO_THREADSAFE_STATICS */
#ifdef __cplusplus
}
#endif


#if defined(DEFINE_ATEXIT)
void atexit(void) { }	// firmware never exits...
#endif

#if !defined(USE_MEM_MGMT)
// These should be moved into the memory management section when it gets written
void * operator new(size_t size) {		// new replacement
	return malloc(size);
}
void * operator new(size_t s, void* d) {		// placement new
	return d;
}
void * operator new[] (size_t size) {
	return malloc(size);
}
void operator delete(void * ptr) {
	if (ptr) free(ptr);
}
void operator delete(void * p, void * const b) { }	// placement delete..hmmm
void operator delete[] (void * ptr) {
	if (ptr) free(ptr);
}
#endif

#ifdef PROGMEM_BUILTIN
//.....................[ <avr/progmem.h>
// Broken progmem in C++. This is a literal cut/paste from <avr/progmem.h>
// This removes the complaint about not setting FCPU and MCU as well as the
// unending and annoying c++ program space errors.
#ifndef __ATTR_CONST__
#define __ATTR_CONST__ __attribute__((__const__))
#endif

#ifndef __ATTR_PROGMEM__
#define __ATTR_PROGMEM__ __attribute__((__progmem__))
#endif

#ifndef __ATTR_PURE__
#define __ATTR_PURE__ __attribute__((__pure__))
#endif

#define PROGMEM __ATTR_PROGMEM__
typedef char PROGMEM prog_char;
# define PSTR(s) (__extension__({static char __c[] PROGMEM = (s); &__c[0];}))

#define __LPM_classic__(addr)   \
(__extension__({                \
    uint16_t __addr16 = (uint16_t)(addr); \
    uint8_t __result;           \
    __asm__                     \
    (                           \
        "lpm" "\n\t"            \
        "mov %0, r0" "\n\t"     \
        : "=r" (__result)       \
        : "z" (__addr16)        \
        : "r0"                  \
    );                          \
    __result;                   \
}))
#define __LPM(addr)         __LPM_classic__(addr)
#define pgm_read_byte_near(address_short) __LPM((uint16_t)(address_short))
#define pgm_read_byte(address_short)    pgm_read_byte_near(address_short)
#endif

#define XMEGA_DEFINED   (defined(__AVR_ATxmega64A3__) || defined(__AVR_ATxmega128A3__) \
    || defined(__AVR_ATxmega256A3__) || defined(__AVR_ATxmega32A4__))

#define DUAL_USART	(defined(__AVR_ATmega128__) || defined(__AVR_ATmega644P__) \
	|| defined(__AVR_ATmega1281__) || defined(__AVR_ATmega162__))

#endif /* __AVR__*/

char    Hex2Char(char *  s) {
    int val = 0;
    int len = strlen(s);
    for (int i = 0; i < len; i++) {
        wchar_t ch = s[i];
        if ('0' <= ch && ch <= '9') val = 16 * val + (ch - '0');
        else if ('a' <= ch && ch <= 'f') val = 16 * val + (10 + ch - 'a');
        else if ('A' <= ch && ch <= 'F') val = 16 * val + (10 + ch - 'A');
        else {
            ;
        }
    }
    if (val >= 3) {/* pdt */
        ;
    }
    return (char) val;
}
char *  Char2Hex(char ch) {
    char* format = new char[10];
    sprintf(format, "0x%04x", ch);
    return format;
}


#endif	/* _STDCPP_COMMON_H_ */
